-
Notifications
You must be signed in to change notification settings - Fork 2.6k
HAZEI Onboarding #1000
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 19.0
Are you sure you want to change the base?
HAZEI Onboarding #1000
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small things here :)
estate/__init__.py
Outdated
| @@ -0,0 +1 @@ | |||
| from . import models No newline at end of file | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
End of file line is missing here
estate/__manifest__.py
Outdated
| 'summary' : 'Real Estate Management Tutorial', | ||
| 'application': True, | ||
|
|
||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
End of file line is missing here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work here ! :D
I didn't highlight them all but be careful about the naming of the ids/files/names according to: https://www.odoo.com/documentation/19.0/contributing/development/coding_guidelines.html
estate/models/estate_property.py
Outdated
| name = fields.Char(string="Title", required=True) | ||
| description = fields.Text() | ||
| postcode = fields.Char() | ||
| date_availability = fields.Date(copy=False, readonly=True, default=date.today() + relativedelta(months=3)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| date_availability = fields.Date(copy=False, readonly=True, default=date.today() + relativedelta(months=3)) | |
| date_availability = fields.Date(copy=False, readonly=True, default=lambda self: date.today() + relativedelta(months=3)) |
If you don't do this, it will only be evaluated one time and not work tomorrow on a long running instance.
estate/models/estate_property.py
Outdated
| string='garden_orientation', | ||
| selection=[('north', 'North'), ('south', 'South'), | ||
| ('east', 'East'), ('west', 'West')]) | ||
| active = fields.Boolean(default=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| active = fields.Boolean(default=False) | |
| active = fields.Boolean() |
False is already the default for Boolean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @hazei-odoo 👋
As you asked, I checked your development. My comments are mainly about python conventions 👋.
Also do not forget to add a title and a description to your PR. The title must have the same structure than a commit title -> [ADD/IMP/FIX...] app: the purpose of the pr (must start by a verb). And for the description, it must mainly explain why the pr is doing this and not how.
Thanks for you work 😃!
estate/models/estate_property.py
Outdated
| from odoo import models, fields, api | ||
| from datetime import date | ||
| from dateutil.relativedelta import relativedelta | ||
| from odoo.exceptions import UserError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The imports should also be sorted alphabetically. I would add that external imports (all imports “date...” for example) must be imported first, followed by internal imports (starting with “from odoo”).
estate/models/estate_property.py
Outdated
| _description = "Real Estate Property" | ||
|
|
||
| name = fields.Char(string="Title", required=True) | ||
| Property_Type = fields.Text() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be property_type. Variables use only lowercase letters. Uppercase letters are used by constants and classes.
Variable -> this_is_a_variable =
constant -> THIS_IS_A_CONSTANT
class -> ThisIsAClass
estate/models/estate_property.py
Outdated
| ) | ||
|
|
||
| def action_set_sold(self): | ||
| if (self.state != "Cancelled"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need of the parenthesis. The != evaluate if the two elements are similar and will return a boolean value in any case.
| if (self.state != "Cancelled"): | |
| if self.state != "Cancelled": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job !
Not much to say. Did like I would on a real review.
| selection=[ | ||
| ('new', 'New'), | ||
| ('offer_received', 'Offer Received'), | ||
| ('offer_accepted', 'Offer Accepted'), | ||
| ('sold', 'Sold'), | ||
| ('cancelled', 'Cancelled')] | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a constant, so it should go outside the class and be given a more consistent name like PROPERTY_STATES
| def action_set_sold(self): | ||
| if self.state != "cancelled": | ||
| self.state = "sold" | ||
| else: | ||
| raise UserError("A cancelled property can not be sold") | ||
| return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def action_set_sold(self): | |
| if self.state != "cancelled": | |
| self.state = "sold" | |
| else: | |
| raise UserError("A cancelled property can not be sold") | |
| return True | |
| def action_set_sold(self): | |
| if self.state == "cancelled": | |
| raise UserError("A cancelled property can not be sold") | |
| self.state = "sold" | |
| return True |
More concise and extendable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also what would happen here if self contains more than 1 property ?
| def action_set_sold(self): | ||
| if self.state != "cancelled": | ||
| self.state = "sold" | ||
| else: | ||
| raise UserError("A cancelled property can not be sold") | ||
| return True | ||
|
|
||
| def action_set_cancelled(self): | ||
| if (self.state != "sold"): | ||
| self.state = "cancelled" | ||
| else: | ||
| raise UserError("A sold property can not be cancelled") | ||
| return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per attribute ordering (coding guidelines), this should go lower in the file
| def action_set_cancelled(self): | ||
| if (self.state != "sold"): | ||
| self.state = "cancelled" | ||
| else: | ||
| raise UserError("A sold property can not be cancelled") | ||
| return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def action_set_cancelled(self): | |
| if (self.state != "sold"): | |
| self.state = "cancelled" | |
| else: | |
| raise UserError("A sold property can not be cancelled") | |
| return True | |
| def action_set_cancelled(self): | |
| if self.state == "sold": | |
| raise UserError("A sold property can not be cancelled") | |
| self.state = "cancelled" | |
| return True |
No parentheses around if, and more concise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also what would happen here if self contains more than 1 property ?
| @api.depends('living_area', 'garden_area') | ||
| def _compute_total_area(self): | ||
| for property in self: | ||
| property.total_area = property.living_area + (property.garden_area or 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| property.total_area = property.living_area + (property.garden_area or 0) | |
| property.total_area = property.living_area + property.garden_area |
garden_area is an integer, it cannot be False
| def _compute_best_price(self): | ||
| for record in self: | ||
| if record.offer_ids: | ||
| record.best_price = max(record.offer_ids.mapped('price')) if record.offer_ids else 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def _compute_best_price(self): | |
| for record in self: | |
| if record.offer_ids: | |
| record.best_price = max(record.offer_ids.mapped('price')) if record.offer_ids else 0 | |
| def _compute_best_price(self): | |
| for record in self: | |
| record.best_price = max(record.offer_ids.mapped('price')) if record.offer_ids else 0 |
First check not needed
| _check_expected_price = models.Constraint( | ||
| 'CHECK(expected_price >= 0)', 'The expected price must be strictly positive.') | ||
|
|
||
| _check_selling_price = models.Constraint( | ||
| 'CHECK(selling_price > 0)', 'The selling price must be positive.') | ||
|
|
||
| @api.constrains('selling_price', 'expected_price') | ||
| def _check_selling_price_expected_price(self): | ||
| for record in self: | ||
| if record.selling_price == 0: | ||
| continue | ||
| if float_compare(record.selling_price, 0.9 * record.expected_price, precision_digits=2) == -1: | ||
| raise UserError("The selling price must be at least 90% of the expected price.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per attribute ordering this needs to be higher
| def action_refuse(self): | ||
| for offer in self: | ||
| if offer.state != 'accepted': | ||
| offer.state = 'refused' | ||
| else: | ||
| raise UserError("An accepted offer cannot be refused.") | ||
| return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def action_refuse(self): | |
| for offer in self: | |
| if offer.state != 'accepted': | |
| offer.state = 'refused' | |
| else: | |
| raise UserError("An accepted offer cannot be refused.") | |
| return True | |
| def action_refuse(self): | |
| if any(offer.state == 'accepted' for offer in self): | |
| raise UserError("An accepted offer cannot be refused.") | |
| self.state = 'refused' | |
| return True |
More concise
| ], | ||
| 'installable': True, | ||
| 'application': True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ], | |
| 'installable': True, | |
| 'application': True, | |
| ], | |
| 'application': True, |
default value for installable is already True

No description provided.